package com.example.mvvmcoroutineexample

import android.content.Context
import android.content.res.Configuration
import android.view.View
import android.view.WindowInsets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.setPadding

class RootViewDeferringInsetsCallback(
    val persistentInsetTypes: Int,
    val deferredInsetTypes: Int,
    val orientationInsetTypes: Int,
    val gestureInsetTypes: Int,
    val context: Context
) :
    WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE),
    OnApplyWindowInsetsListener {
    init {
        require(persistentInsetTypes and deferredInsetTypes and orientationInsetTypes == 0) {
            "persistentInsetTypes and deferredInsetTypes can not contain any of " +
                    " same WindowInsetsCompat.Type values"
        }
    }

    private var view: View? = null
    private var lastWindowInsets: WindowInsetsCompat? = null
    private var deferredInsets: Boolean = false
    private var isLandscape: Boolean? = null

    override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
        view = v;
        lastWindowInsets = insets
        isLandscape =
            context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE

        val types = when {
            deferredInsets -> persistentInsetTypes
            isLandscape!! -> orientationInsetTypes
            else -> persistentInsetTypes or deferredInsetTypes
        }

        val typeInsets = insets.getInsets(types)
        val persistentInsets = insets.getInsets(persistentInsetTypes)
        if (isLandscape!!) {
            v.setPadding(
                typeInsets.left,
                persistentInsets.top,
                typeInsets.right,
                persistentInsets.bottom
            )
        } else {
            val gestureInsets = insets.getInsets(gestureInsetTypes)
            v.setPadding(gestureInsets.left, typeInsets.top, gestureInsets.right, typeInsets.bottom)
        }

        return WindowInsetsCompat.CONSUMED
    }

    override fun onPrepare(animation: WindowInsetsAnimationCompat) {
        if (animation.typeMask and deferredInsetTypes != 0) {
            deferredInsets = true
        }
    }

    override fun onProgress(
        insets: WindowInsetsCompat,
        runningAnimations: MutableList<WindowInsetsAnimationCompat>
    ): WindowInsetsCompat {
        return insets
    }

    override fun onEnd(animation: WindowInsetsAnimationCompat) {
        if (deferredInsets && (animation.typeMask and deferredInsetTypes) != 0) {
            deferredInsets = false
            if (lastWindowInsets != null && view != null) {
                ViewCompat.dispatchApplyWindowInsets(view!!, lastWindowInsets!!)
            }
        }
    }
}
